/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.openide.explorer.view;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.awt.Point;
import java.awt.Cursor;
import java.io.IOException;
import org.openide.TopManager;
import org.openide.NotifyDescriptor;
import org.openide.nodes.Node;
import org.openide.nodes.NodeTransfer;
import org.openide.TopManager;
import org.openide.util.datatransfer.*;
import org.openide.util.UserCancelException;
import org.openide.util.NbBundle;
/** Class that provides methods for common tasks needed during
* drag and drop when working with explorer views.
*
* @author Dafe Simonek
*/
final class DragDropUtilities extends Object {
/** No need to instantiate this class */
private DragDropUtilities () {
}
/** Utility method - chooses and returns right cursor
* for given user drag action.
*/
static Cursor chooseCursor (int dragAction, boolean canDrop) {
Cursor result = null;
switch (dragAction) {
case DnDConstants.ACTION_COPY:
case DnDConstants.ACTION_COPY_OR_MOVE:
result = canDrop ? DragSource.DefaultCopyDrop
: DragSource.DefaultCopyNoDrop;
break;
case DnDConstants.ACTION_MOVE:
result = canDrop ? DragSource.DefaultMoveDrop
: DragSource.DefaultMoveNoDrop;
break;
case DnDConstants.ACTION_LINK:
result = canDrop ? DragSource.DefaultLinkDrop
: DragSource.DefaultLinkNoDrop;
break;
default:
result = canDrop ? DragSource.DefaultCopyDrop
: DragSource.DefaultCopyNoDrop;
break;
}
return result;
}
/** Utility method.
* @return true if given node supports given action,
* false otherwise.
*/
static boolean checkNodeForAction (Node node, int dragAction) {
if (node.canCut() &&
((dragAction == DnDConstants.ACTION_MOVE) ||
(dragAction == DnDConstants.ACTION_COPY_OR_MOVE)))
return true;
if (node.canCopy() &&
((dragAction == DnDConstants.ACTION_COPY) ||
(dragAction == DnDConstants.ACTION_COPY_OR_MOVE) ||
(dragAction == DnDConstants.ACTION_LINK) ||
(dragAction == DnDConstants.ACTION_REFERENCE)))
return true;
// hmmm, conditions not satisfied..
return false;
}
/** Gets right transferable of given nodes (according to given
* drag action) and also converts the transferable.<br>
* Can be called only with correct action constant.
* @return The transferable.
*/
static Transferable getNodeTransferable (Node[] nodes, int dragAction)
throws IOException {
Transferable[] tArray = new Transferable[nodes.length];
//System.out.println("Sel count: " + nodes.length); // NOI18N
for (int i = 0; i < nodes.length; i++) {
ExClipboard cb = TopManager.getDefault ().getClipboard ();
if (dragAction == DnDConstants.ACTION_MOVE)
tArray[i] = cb.convert (nodes[i].clipboardCut());
else
tArray[i] = cb.convert (nodes[i].clipboardCopy());
}
if (tArray.length == 1)
// only one node, so return regular single transferable
return tArray[0];
// enclose the transferables into multi transferable
return new ExTransferable.Multi(tArray);
}
/** Returns transferable of given node
* @return The transferable.
*/
static Transferable getNodeTransferable (Node node, int dragAction)
throws IOException {
return getNodeTransferable(new Node[] { node }, dragAction);
}
/** Performs the drop. Performs paste on given paste type.
*/
static void performDrop (PasteType type) {
//System.out.println("performing drop...."); // NOI18N
try {
Transferable trans = type.paste();
/*Clipboard clipboard = TopManager.getDefault().getClipboard();
if (trans != null) {
ClipboardOwner owner = trans instanceof ClipboardOwner ?
(ClipboardOwner)trans
:
new StringSelection ("");
clipboard.setContents(trans, owner);
}*/
} catch (UserCancelException exc) {
// ignore - user just pressed cancel in some dialog....
} catch (java.io.IOException e) {
org.openide.TopManager.getDefault().notifyException(e);
}
}
/** Returns array of paste types for given transferable.
* If given transferable contains multiple transferables,
* multi paste type which encloses pate types of all contained
* transferables is returned.
* Returns empty array if given node did not accepted the transferable
* (or some sub-transferables in multi transferable)
*
* @param node given node to ask fro paste types
* @param trans transferable to discover
*/
static PasteType[] getPasteTypes (Node node, Transferable trans) {
// find out if given transferable is multi
boolean isMulti = false;
try {
isMulti = trans.isDataFlavorSupported(ExTransferable.multiFlavor);
} catch (Exception e) {
// patch to get the Netbeans start under Solaris
// [PENDINGworkaround]
}
if (!isMulti) {
// only single, so return paste types
return node.getPasteTypes(trans);
} else {
// multi transferable, we must do extra work
try {
MultiTransferObject obj = (MultiTransferObject)
trans.getTransferData(ExTransferable.multiFlavor);
int count = obj.getCount();
Transferable[] t = new Transferable[count];
PasteType[] p = new PasteType[count];
PasteType[] curTypes = null;
// extract default paste types of transferables
for (int i = 0; i < count; i++) {
t[i] = obj.getTransferableAt(i);
curTypes = node.getPasteTypes(t[i]);
// return if not accepted
if (curTypes.length == 0)
return curTypes;
p[i] = curTypes[0];
}
// return new multi paste type
return new PasteType[] { new MultiPasteType(t, p) };
} catch (UnsupportedFlavorException e) {
// ignore and return empty array
}
catch (IOException e) {
// ignore and return empty array
}
}
return new PasteType[0];
}
/** Notifies user that the drop was not succesfull. */
static void dropNotSuccesfull () {
TopManager.getDefault().notify(new NotifyDescriptor.Message(
NbBundle.getBundle(TreeViewDropSupport.class).
getString("MSG_NoPasteTypes"),
NotifyDescriptor.WARNING_MESSAGE)
);
}
/** Paste type used when in clipbopard is MultiTransferable */
static final class MultiPasteType extends PasteType {
// Attributes
/** Array of transferables */
Transferable[] t;
/** Array of paste types */
PasteType[] p;
// Operations
/** Constructs new MultiPasteType for the given
* transferables and paste types.*/
MultiPasteType(Transferable[] t, PasteType[] p) {
this.t = t;
this.p = p;
}
/** Performs the paste action.
* @return Transferable which should be inserted into the
* clipboard after paste action. It can be null, which means
* that clipboard content should be cleared.
*/
public Transferable paste() throws IOException {
int size = p.length;
Transferable[] arr = new Transferable[size];
// perform paste for all source transferables
for (int i = 0; i < size; i++) {
//System.out.println("Pasting #" + i); // NOI18N
arr[i] = p[i].paste();
}
return new ExTransferable.Multi(arr);
}
} // end of MultiPasteType
}
/*
* Log
* 8 Gandalf 1.7 1/13/00 Ian Formanek NOI18N
* 7 Gandalf 1.6 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 6 Gandalf 1.5 9/22/99 Jesse Glick ExClipboard.Convertor
* changed signature to accommodate converting to node selection.
* 5 Gandalf 1.4 6/8/99 Ian Formanek ---- Package Change To
* org.openide ----
* 4 Gandalf 1.3 5/16/99 David Simonek debug prints commented
* 3 Gandalf 1.2 4/30/99 David Simonek
* 2 Gandalf 1.1 4/28/99 David Simonek drag and drop in tree now
* supports multi-selection
* 1 Gandalf 1.0 4/27/99 David Simonek
* $
*/